package com.ouwen.smartpay.service.chain.slots.auth;

import com.fm.common.emuns.ResponseCode;
import com.fm.core.common.boot.Apps;
import com.fm.core.common.facade.BizResultBase;
import com.fm.core.utils.Collections3;
import com.ouwen.smartpay.entity.Partner;
import com.ouwen.smartpay.entity.PartnerService;
import com.ouwen.smartpay.exception.AuthSlotException;
import com.ouwen.smartpay.openapi.order.ServiceOrder;
import com.ouwen.smartpay.service.PartnerServiceService;
import com.ouwen.smartpay.service.chain.context.Context;
import com.ouwen.smartpay.service.chain.slotchain.AbstractLinkedProcessorSlot;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;

import java.util.List;
import java.util.stream.Collectors;

/**
 * @author <a href="http://youngitman.tech">青年IT男</a>
 * @version v1.0.0
 * @className AuthSlot
 * @description 权限验证
 * @JunitTest: {@link  }
 * @date 2020-04-26 13:55
 **/
public class AuthSlot extends AbstractLinkedProcessorSlot<ServiceOrder> {

    Logger logger = LoggerFactory.getLogger(getClass());

    private com.ouwen.smartpay.service.PartnerService  partnerService;

    private PartnerServiceService partnerServiceService;

    @Override
    public void entry(Context context, ServiceOrder serviceOrder, Object... args) throws Throwable {

        try {

            ApplicationContext applicationContext = Apps.getApplicationContext();

            partnerService = applicationContext.getBean(com.ouwen.smartpay.service.PartnerService .class);

            partnerServiceService = applicationContext.getBean(PartnerServiceService.class);

            Partner partner = partnerService.findPartner(serviceOrder.getPartnerId(), serviceOrder.getSubPartnerId());

            if (partner == null || partner.getStatus() == 0) {

                throw new AuthSlotException("商户信息未查询到或被禁用");

            } else {

                //校验是否有权限
                List<PartnerService> partnerServices = partnerServiceService.findPartnerServices(serviceOrder.getPartnerId(), serviceOrder.getSubPartnerId());

                if (Collections3.isEmpty(partnerServices)) {

                    throw new AuthSlotException("商户未配置任何服务");

                } else {

                    //对商户服务进行验证
                    List<PartnerService> partnerServiceList = partnerServices.parallelStream()
                            .filter(_partnerService -> serviceOrder.getService().equals(_partnerService.getServiceName()))
                            .filter(_partnerService -> serviceOrder.getVersion().equals(_partnerService.getServiceVersion()))
                            .filter(_partnerService -> {
                                if (serviceOrder.getGroup() == null && _partnerService.getServiceGroup() == null) {
                                    return true;
                                }
                                if (serviceOrder.getGroup() != null && _partnerService.getServiceGroup() != null
                                        && serviceOrder.getGroup().equals(_partnerService.getServiceGroup())) {
                                    return true;
                                }
                                return false;
                            })
                            .collect(Collectors.toList());

                    if (Collections3.isEmpty(partnerServiceList)) {

                        throw new AuthSlotException(String.format("商户请求服务【%s】版本【%s】分组【%s】:未配置", serviceOrder.getService(), serviceOrder.getVersion(), serviceOrder.getGroup()));

                    }
                }
            }

            fireEntry(context, serviceOrder, args);

        } catch (Exception e) {

            logger.info("权限验证异常:{}", e.getMessage());

            BizResultBase result = new BizResultBase();

            result.setRespCode(ResponseCode.FAIL.code());

            result.setRespMsg(ResponseCode.FAIL.message());

            result.setDescription(e.getMessage());

            exit(context, serviceOrder, args, result);

        }
    }


    @Override
    public void exit(Context context, Object... args) {

        fireExit(context, args);

    }
}
